local skynet = require "skynet"
local filename = "slotmgr.lua"
local filelog = require "filelog"
local queue = require "skynet.queue"
local base = require "base"
local redisdao = require "redisdao"
local tabletool = require "tabletool"
local json = require "cjson"
json.encode_sparse_array(true,1,1)

local SlotTool = require "slottool"
require "lhjenum"

------------
--枚举类

--系统输钱上限基值,默认10万
local SystemLoseLimit_Base = 1000000

--系统输钱上限控制系数
local SystemLoseLimit_Factor = 0.08

--开奖类型
local LotteryType = {
    LOTTERY_TYPE_HIT = 1,   --必中类型
    LOTTERY_TYPE_NOHIT = 2, --必不中
    LOTTERY_TYPE_NORMAL = 3,--正常开奖
}

--线数组
--线分布在一个3 * 5 的矩阵内
local line_list = {
    [1] = {21,22,23,24,25},      --线1，矩阵坐标(2,1),(2,2),(2,3),(2,4),(2,5)
    [2] = {11,12,13,14,15},      --线2，矩阵坐标(1,1),(1,2),(1,3),(1,4),(1,5)
    [3] = {31,32,33,34,35},      --线3，矩阵坐标(3,1),(3,2),(3,3),(3,4),(3,5)
    [4] = {11,22,33,24,15},      --线4，矩阵坐标(1,1),(2,2),(3,3),(2,4),(1,5)
    [5] = {31,22,13,24,35},      --线5，矩阵坐标(3,1),(2,2),(1,3),(2,4),(3,5)
    [6] = {11,12,23,14,15},      --线6，矩阵坐标(1,1),(1,2),(2,3),(1,4),(1,5)
    [7] = {31,32,23,34,35},      --线7，矩阵坐标(3,1),(3,2),(2,3),(3,4),(3,5)
    [8] = {21,32,33,34,25},      --线8，矩阵坐标(2,1),(3,2),(3,3),(3,4),(2,5)
    [9] = {21,12,13,14,25},      --线9，矩阵坐标(2,1),(1,2),(1,3),(1,4),(2,5)
}

--初始图片列表
--一个3*5的数组
local Init_picture_list = {
    101,102,104,103,101,    --第1行
    106,105,101,105,106,    --第2行
    107,103,108,107,108,    --第3行
}

--转盘配置表
local Turntable_conf = {
    104,102,108,101,103,113,106,104,
    102,101,107,113,105,103,101,104,
    106,113,105,102,101,103,107,113,
}

--图标位置映射表
local Picture_index_map_list = nil

--图标id
local Picture_id = {
    101,    --银斧
    102,    --银枪
    103,    --金刀
    104,    --鲁
    105,    --林
    106,    --宋
    107,    --替天行道
    108,    --忠义堂
    109,    --待定
    110,    --待定
    111,    --水浒传，BAR，触发小玛丽游戏
    112,    --待定，钻石
    113,    --exit，特殊图标，小玛丽游戏出口
}

--特殊图标id
local SpecialPictureId = {
    SPECIAL_PICTURE_ID_BAR = 111,       --BAR，可以代替其他图片在第一个也可以）
    SPECIAL_PICTURE_ID_DIAMOND = 112,   --钻石可以触发转盘抽奖
    SPECIAL_PICTURE_ID_EXIT = 113,      --exit,小玛丽游戏出口
    SPECIAL_PICTURE_ID_LEFT_THREE_LINK = 31110,   --左3连
    SPECIAL_PICTURE_ID_RIGHT_THREE_LINK = 30111,  --右3连
    SPECIAL_PICTURE_ID_FOUR_LINK = 41111,         --4连
}

----------------------
--数据表，可以改变

--倍率列表
--key为：图标个数 + 图标id
--[2101] = 2 表示：2个西梅的倍率为2倍
--
local Odds_list = {
    --银斧
    [2101] = nil,
    [3101] = 2,
    [4101] = 5,
    [5101] = 20,
    [6101] = 50,
    --银枪
    [2102] = nil,
    [3102] = 3,
    [4102] = 10,
    [5102] = 40,
    [6102] = 100,
    --金刀
    [2103] = nil,
    [3103] = 5,
    [4103] = 15,
    [5103] = 60,
    [6103] = 150,
    --鲁
    [2104] = nil,
    [3104] = 7,
    [4104] = 20,
    [5104] = 100,
    [6104] = 250,
    --林
    [2105] = nil,
    [3105] = 10,
    [4105] = 30,
    [5105] = 160,
    [6105] = 400,
    --宋
    [2106] = nil,
    [3106] = 15,
    [4106] = 40,
    [5106] = 200,
    [6106] = 500,
    --替天行道
    [2107] = nil,
    [3107] = 20,
    [4107] = 80,
    [5107] = 400,
    [6107] = 1000,
    --忠义堂
    [2108] = nil,
    [3108] = 50,
    [4108] = 200,
    [5108] = 1000,
    [6108] = 2500,
    --待定
    [2109] = nil,
    [3109] = nil,
    [4109] = nil,
    [5109] = nil,
    --待定
    [2110] = nil,
    [3110] = nil,
    [4110] = nil,
    [5110] = nil,
    --水浒传，BAR
    [2111] = nil,
    [3111] = nil,
    [4111] = nil,
    [5111] = 2000,
    [6111] = 5000,
    --待定，钻石
    [2112] = nil,
    [3112] = nil,
    [4112] = nil,
    [5112] = nil,
}

--小玛丽赔率表
local Littlemary_odds_list = {
    [101] = 2,
    [102] = 5,
    [103] = 10,
    [104] = 20,
    [105] = 50,
    [106] = 70,
    [107] = 100,
    [108] = 200,
    
    --连出赔率
    [31110] = 20,
    [30111] = 20,
    [41111] = 500,
}

--小玛丽权重表
local Littlemary_weight_list = {
    [1] = {    --外圈权值表
        [0]   = 2000,    --不中奖
        [101] = 3000,
        [102] = 1200,
        [103] = 600,
        [104] = 300,
        [105] = 100,
        [106] = 80,
        [107] = 0,
        [108] = 0,
        [111] = 0,
        [113] = 2500,    --中exit
    },
    [2] = {    --内圈多武器权值表
        [101] = {
            [1] = 40,    --40%概率单铁斧
            [2] = 60,    --60%概率双铁斧
        },
        [102] = {
            [1] = 60,    --60%概率单银枪
            [2] = 40,    --40%概率双银枪
        },
        [103] = {
            [1] = 80,    --80%概率单金刀
            [2] = 20,    --20%概率双金刀
        },
    },
    [3] = {    --内圈连出权值表
        [0] = 90,       --不中奖
        [SpecialPictureId.SPECIAL_PICTURE_ID_LEFT_THREE_LINK] = 5,  --左三连
        [SpecialPictureId.SPECIAL_PICTURE_ID_RIGHT_THREE_LINK] = 5, --右三连
        [SpecialPictureId.SPECIAL_PICTURE_ID_FOUR_LINK] = nil,      --四连
    },
}

--转盘倍率表
--key:钻石个数， value：对应转盘倍率表
local Truntable_odds_list = {
    [3] = {
        [1] = 10,
        [2] = 15,
        [3] = 20,
        [4] = 50,
        [5] = 100,
        [6] = 200,
        [7] = 300,
        [8] = 400,
        [9] = 500,
    },
    [4] = {
        [1] = 50,
        [2] = 100,
        [3] = 200,
        [4] = 400,
        [5] = 600,
        [6] = 800,
        [7] = 1000,
        [8] = 1500,
        [9] = 2000,
    },
    [5] = {
        [1] = 100,
        [2] = 300,
        [3] = 500,
        [4] = 800,
        [5] = 1200,
        [6] = 1500,
        [7] = 2000,
        [8] = 3000,
        [9] = 4000,
    },
}

--转盘权值表
local Turntable_weight_list = {
    [3] = {
        [1] = 5,
        [2] = 10,
        [3] = 20,
        [4] = 52,
        [5] = 8,
        [6] = 5,
        [7] = 0,
        [8] = 0,
        [9] = 0,
    },
    [4] = {
        [1] = 8,
        [2] = 12,
        [3] = 18,
        [4] = 32,
        [5] = 15,
        [6] = 10,
        [7] = 5,
        [8] = 0,
        [9] = 0,
    },
    [5] = {
        [1] = 4,
        [2] = 14,
        [3] = 25,
        [4] = 30,
        [5] = 14,
        [6] = 8,
        [7] = 5,
        [8] = 0,
        [9] = 0,
    },
}


--图标权重列表
local Weight_list = {
    [1] = { --第1列
        [101] = 1900,   --西梅
        [102] = 1700,   --葡萄
        [103] = 1600,   --猕猴桃
        [104] = 1300,   --樱桃
        [105] = 1000,   --苹果
        [106] = 900,    --西瓜
        [107] = 800,    --柠檬
        [108] = 600,    --橙子
        [109] = 0,      --铃铛
        [110] = 0,      --777
        [111] = 200,    --BAR
        [112] = 0,      --钻石
    },
    [2] = { --第2列
        [101] = 1900,   --西梅
        [102] = 1700,   --葡萄
        [103] = 1800,   --猕猴桃
        [104] = 1500,   --樱桃
        [105] = 1000,   --苹果
        [106] = 900,    --西瓜
        [107] = 550,    --柠檬
        [108] = 500,    --橙子
        [109] = 0,      --铃铛
        [110] = 0,      --777
        [111] = 150,    --BAR
        [112] = 0,      --钻石
    },
    [3] = { --第3列
        [101] = 1700,   --西梅
        [102] = 1750,   --葡萄
        [103] = 1300,   --猕猴桃
        [104] = 1250,   --樱桃
        [105] = 1200,   --苹果
        [106] = 1300,   --西瓜
        [107] = 700,    --柠檬
        [108] = 700,    --橙子
        [109] = 0,      --铃铛
        [110] = 0,      --777
        [111] = 100,    --BAR
        [112] = 0,      --钻石
    },
    [4] = { --第4列
        [101] = 1800,   --西梅
        [102] = 1250,   --葡萄
        [103] = 1600,   --猕猴桃
        [104] = 1300,   --樱桃
        [105] = 1100,   --苹果
        [106] = 1100,   --西瓜
        [107] = 900,    --柠檬
        [108] = 800,    --橙子
        [109] = 0,      --铃铛
        [110] = 0,      --777
        [111] = 150,    --BAR
        [112] = 0,      --钻石
    },
    [5] = { --第5列
        [101] = 1500,   --西梅
        [102] = 1800,   --葡萄
        [103] = 1600,   --猕猴桃
        [104] = 1350,   --樱桃
        [105] = 1200,   --苹果
        [106] = 900,    --西瓜
        [107] = 850,    --柠檬
        [108] = 600,    --橙子
        [109] = 0,      --铃铛
        [110] = 0,      --777
        [111] = 200,    --BAR
        [112] = 0,      --钻石
    },
}

--系统库存概率表
--S = 库存值 / 底分
local S_list = {
    [1] = { -- S <= -5万
        nohit = 0.50,   --必不中概率
        normal = 0.50,  --正常开奖概率
        hit = 0.00,     --必中概率
    },
    [2] = { -- -5万<S<-1万
        nohit = 0.40,   --必不中概率
        normal = 0.60,  --正常开奖概率
        hit = 0.00,     --必中概率
    },
    [3] = { -- -1万<=S<-1000
        nohit = 0.20,   --必不中概率
        normal = 0.80,  --正常开奖概率
        hit = 0.00,     --必中概率
    },
    [4] = { -- -1000<=S<=5000
        nohit = 0.00,   --必不中概率
        normal = 1.00,  --正常开奖概率
        hit = 0.00,     --必中概率
    },
    [5] = { -- 5000<S<=2万
        nohit = 0.00,   --必不中概率
        normal = 0.80,  --正常开奖概率
        hit = 0.20,     --必中概率
    },
    [6] = { -- 2万<S<10万
        nohit = 0.00,   --必不中概率
        normal = 0.70,  --正常开奖概率
        hit = 0.30,     --必中概率
    },
    [7] = { -- S>10万
        nohit = 0.00,   --必不中概率
        normal = 0.50,  --正常开奖概率
        hit = 0.50,     --必中概率
    },
}

--开奖权值表
local Jackpot_weight_list = {
    [1] = {
        low = 100,  --中奖励1的权重
        [2] = 0,    --中奖励2的权重
        [3] = 0,    --中奖励3的权重
        [4] = 0,    --中奖励4的权重
        [5] = 0,    --中奖励5的权重
        [6] = 0,    --中奖励6的权重
    },
    [2] = {
        [1] = 60,   --中奖励1的权重
        [2] = 30,   --中奖励2的权重
        [3] = 10,   --中奖励3的权重
        [4] = 0,    --中奖励4的权重
        [5] = 0,    --中奖励5的权重
        [6] = 0,    --中奖励6的权重
    },
    [3] = {
        [1] = 50,   --中奖励1的权重
        [2] = 30,   --中奖励2的权重
        [3] = 10,   --中奖励3的权重
        [4] = 10,   --中奖励4的权重
        [5] = 0,    --中奖励5的权重
        [6] = 0,    --中奖励6的权重
    },
}

--奖池奖励列表
local Jackpot_award_list = {
    [1] = 1,    --获取奖池1%
    [2] = 5,    --获取奖池5%
    [3] = 8,    --获取奖池8%
    [4] = 10,   --获取奖池10%
    [5] = 15,   --获取奖池15%
    [6] = 20,   --获取奖池20%
}

--小倍奖权值表
local Minmulti_weight_list = {
    [0] = 30,    --必不中
    [1] = 70,    --必中
}

--------------------------
--辅助表

--图标概率表
local Prob_list = nil

--总权值表
local Total_weight_list = nil

--小倍必中开奖组合,1~8线16种，9线1000种
local HitLottery_minmulti_list = nil

--小倍必中开奖列表的索引表
--key为押注线数，value可选组合列表
local HitLottery_minmulti_index_list = nil

--必不中开奖组合,预设36种
local NoHitLottery_list = {
    {106,106,103,108,103,103,102,101,111,108,105,102,105,108,104,},
    {104,105,102,103,103,102,104,107,106,105,107,102,101,101,106,},
    {106,104,105,107,106,107,111,101,105,106,106,102,107,107,103,},
    {104,101,107,111,105,108,105,103,107,101,103,106,107,103,106,},
    {111,103,102,106,103,107,104,108,111,102,108,103,108,106,105,},
    {105,103,104,105,104,111,102,104,106,108,111,108,103,106,107,},
    {102,111,106,103,104,107,105,105,102,106,105,108,105,107,103,},
    {103,101,103,108,103,106,105,108,101,106,104,106,105,111,104,},
    {111,108,106,102,106,111,107,101,107,108,107,102,105,102,102,},
    {106,104,107,102,105,103,101,103,104,108,102,101,111,106,102,},
    {101,105,102,103,102,103,103,104,101,101,108,108,104,111,103,},
    {104,107,101,105,106,107,104,108,105,106,102,107,102,103,106,},
    {103,105,104,101,107,104,105,102,108,102,107,103,108,102,106,},
    {107,101,102,102,103,111,107,103,101,101,107,102,105,111,101,},
    {105,102,103,101,107,105,103,108,103,106,106,103,107,107,102,},
    {105,104,105,107,104,103,103,107,101,105,103,106,108,101,104,},
    {111,101,108,102,103,105,106,105,108,103,107,102,107,102,101,},
    {103,101,107,104,108,108,107,102,106,106,103,106,102,106,104,},
    {107,103,104,105,108,104,103,102,106,107,107,104,105,101,106,},
    {108,107,101,106,104,107,102,106,103,105,102,105,102,107,102,},
    {101,101,105,103,105,106,107,102,108,103,101,105,108,102,106,},
    {101,101,103,101,106,107,108,107,103,102,103,104,106,104,102,},
    {108,105,102,104,107,107,111,105,108,108,107,111,103,105,101,},
    {105,104,105,106,105,102,104,104,106,107,105,103,104,101,106,},
    {105,107,108,101,106,104,103,102,108,101,106,101,105,101,106,},
    {103,104,103,107,104,101,106,103,106,105,102,107,104,105,108,},
    {108,106,101,104,105,101,103,105,101,101,101,106,103,106,104,},
    {103,111,108,105,106,102,105,102,105,102,107,107,108,101,102,},
    {102,101,108,105,105,104,106,102,104,107,104,106,107,102,107,},
    {106,101,104,104,107,111,104,107,102,108,105,102,107,101,105,},
    {106,103,102,102,106,111,103,104,104,106,106,105,102,104,103,},
    {108,102,104,101,104,101,101,106,105,104,102,101,108,104,104,},
    {105,101,102,101,103,103,105,102,102,103,105,105,104,102,107,},
    {111,107,103,104,107,104,103,106,103,106,105,108,105,106,108,},
    {106,102,108,111,105,105,103,107,102,106,104,107,104,108,103,},
    {104,103,101,102,102,106,107,104,104,108,101,107,106,104,106,},
}

--必中开奖组合,预设9*16=144种
local HitLottery_list = {
    {111,104,104,102,104,102,111,102,108,107,102,103,107,104,102,},
    {101,108,105,104,101,111,106,111,102,104,107,104,106,105,107,},
    {105,103,108,101,107,111,111,103,108,101,107,106,104,103,101,},
    {102,101,111,108,106,111,103,103,105,104,102,103,105,105,106,},
    {104,111,111,103,111,107,102,111,111,101,101,107,106,104,111,},
    {104,107,105,104,104,111,101,101,106,111,102,107,101,106,103,},
    {108,102,108,101,104,106,104,102,102,102,104,105,104,101,103,},
    {101,105,107,105,104,111,101,111,108,103,101,106,101,102,103,},
    {102,106,107,107,106,107,104,101,111,101,103,101,104,104,103,},
    {103,105,107,104,111,108,107,103,103,103,104,102,111,102,102,},
    {102,107,103,108,105,111,106,111,103,102,108,105,101,101,102,},
    {105,101,102,105,111,105,104,107,111,107,105,108,104,106,106,},
    {104,101,101,106,106,111,101,111,106,111,107,102,108,101,107,},
    {108,106,107,105,103,106,106,111,103,104,101,106,101,108,111,},
    {105,103,111,101,106,103,103,103,107,106,106,104,106,111,102,},
    {103,111,101,106,106,106,106,106,108,107,104,106,103,107,103,},
    {104,108,105,105,105,101,101,101,107,111,108,101,105,101,108,},
    {106,111,102,107,103,111,111,106,102,106,111,103,111,105,103,},
    {103,103,103,111,105,107,107,101,108,105,104,101,107,107,103,},
    {106,103,103,107,102,107,101,111,111,111,104,102,102,103,101,},
    {102,104,104,107,104,103,104,103,103,103,103,101,108,108,108,},
    {107,111,111,105,103,106,106,105,106,105,105,105,101,104,105,},
    {111,104,105,106,108,102,102,102,103,111,105,104,102,102,103,},
    {101,107,102,101,111,107,101,111,105,111,103,103,111,105,105,},
    {106,102,111,111,111,102,102,105,102,102,111,107,104,106,108,},
    {102,104,102,108,107,103,111,103,104,111,111,106,104,102,106,},
    {107,103,102,108,108,107,106,103,103,103,111,101,111,111,107,},
    {102,101,104,107,102,105,102,111,103,103,107,111,102,106,105,},
    {106,102,103,111,111,104,104,102,103,106,104,101,106,106,107,},
    {101,102,104,103,101,104,106,105,105,111,102,111,101,107,106,},
    {106,106,111,107,103,108,107,107,103,105,101,103,103,107,102,},
    {104,106,102,111,102,101,105,105,101,104,111,101,103,106,106,},
    {108,105,104,108,111,111,111,105,108,108,111,102,101,104,105,},
    {108,106,104,107,107,111,111,105,104,101,108,102,102,111,102,},
    {105,106,104,108,104,102,107,106,105,106,107,107,106,106,111,},
    {102,102,108,107,102,111,111,101,102,107,103,103,103,106,106,},
    {102,103,101,107,107,107,101,111,101,101,103,101,104,107,102,},
    {111,102,101,104,103,111,111,104,111,105,105,111,101,105,108,},
    {104,102,104,111,105,107,104,102,106,107,105,111,111,102,111,},
    {104,106,111,107,106,105,105,111,106,101,107,102,111,107,103,},
    {102,107,111,104,111,101,104,105,107,103,108,103,111,102,111,},
    {105,104,101,106,105,106,108,101,101,107,104,104,104,105,106,},
    {101,103,102,102,108,107,107,107,108,108,104,102,102,108,106,},
    {111,102,108,101,108,111,102,106,111,111,105,104,101,101,102,},
    {102,101,101,102,111,104,104,104,108,104,101,101,111,105,105,},
    {106,108,106,107,101,106,102,104,111,111,107,111,101,106,105,},
    {105,111,101,102,102,106,106,102,103,107,103,111,103,107,106,},
    {111,104,105,105,102,105,102,103,111,101,102,106,111,103,103,},
    {106,111,101,111,104,103,111,101,105,106,111,107,106,103,102,},
    {104,101,102,105,105,111,101,104,108,105,104,106,111,111,103,},
    {101,106,103,106,104,105,105,111,106,105,104,102,104,105,111,},
    {104,107,105,104,106,106,108,103,111,103,108,107,107,105,108,},
    {111,107,106,104,101,102,101,111,105,111,102,103,107,111,108,},
    {107,107,106,102,108,108,106,111,103,111,106,106,104,106,106,},
    {101,103,105,111,105,106,108,105,102,111,111,102,102,105,105,},
    {111,111,106,107,102,102,111,101,104,103,103,101,101,111,105,},
    {111,102,106,106,106,101,108,104,107,104,108,108,103,105,101,},
    {104,103,111,104,104,101,104,103,106,105,107,111,103,102,105,},
    {107,107,104,105,108,104,101,103,101,101,103,103,111,107,108,},
    {111,105,101,107,104,107,106,101,108,111,107,101,106,104,102,},
    {111,107,108,111,103,105,103,104,107,101,104,108,103,106,111,},
    {105,108,105,105,105,102,111,102,103,108,111,102,107,102,104,},
    {103,101,104,111,111,101,104,111,111,101,106,104,101,111,111,},
    {104,105,107,111,111,103,102,111,104,105,107,104,106,105,105,},
    {101,103,107,107,106,107,108,107,105,102,106,101,106,111,106,},
    {102,104,111,105,111,106,101,101,103,111,103,111,104,103,106,},
    {108,107,102,108,104,106,111,106,102,111,101,106,103,106,104,},
    {101,102,104,101,102,103,104,111,105,107,104,107,106,104,105,},
    {106,106,108,105,111,105,107,101,106,103,104,103,106,107,105,},
    {102,101,111,107,105,108,107,103,105,103,103,105,102,108,105,},
    {106,105,105,104,107,111,107,107,101,101,106,103,107,108,111,},
    {108,101,107,107,106,107,103,105,111,101,101,105,102,104,111,},
    {105,106,111,107,102,104,106,104,101,111,106,108,104,103,108,},
    {105,101,111,111,106,104,101,107,103,111,108,108,104,106,107,},
    {105,106,105,104,105,102,108,106,111,101,105,107,111,111,103,},
    {106,101,102,111,108,105,108,106,101,102,111,111,106,105,106,},
    {104,102,107,101,105,108,104,106,107,101,111,102,101,102,111,},
    {105,107,107,106,111,106,105,101,102,107,102,105,105,101,106,},
    {103,108,106,104,104,104,104,111,103,103,106,103,101,111,101,},
    {105,111,111,106,102,105,105,108,106,103,107,104,104,107,103,},
    {106,106,104,102,107,101,103,106,108,102,101,103,105,102,104,},
    {103,108,104,105,107,105,104,108,105,101,104,103,103,102,104,},
    {104,102,111,103,101,102,105,105,103,103,106,111,111,107,102,},
    {101,103,107,103,103,101,111,111,108,105,104,105,108,101,103,},
    {105,102,103,102,105,105,102,104,105,101,111,108,105,107,108,},
    {105,106,102,103,103,106,104,103,103,111,108,101,105,102,102,},
    {104,111,101,106,108,102,101,104,107,108,103,102,104,102,102,},
    {104,103,103,102,106,106,106,106,103,108,111,104,107,101,103,},
    {107,106,111,111,101,111,108,101,105,104,103,101,111,111,102,},
    {105,111,102,105,103,101,101,101,111,106,111,102,103,106,107,},
    {102,101,105,104,111,111,102,106,105,105,102,111,111,106,107,},
    {111,107,102,105,108,103,102,101,102,108,111,105,106,107,101,},
    {104,102,101,104,104,104,104,102,103,101,105,101,104,102,101,},
    {104,102,102,105,105,105,108,111,107,101,111,103,102,104,104,},
    {105,111,103,104,103,103,104,111,104,108,101,104,106,106,103,},
    {106,101,111,111,105,103,104,111,104,106,102,103,102,111,103,},
    {102,102,106,101,105,111,104,104,111,106,107,104,101,103,103,},
    {106,103,101,105,102,103,101,107,107,107,103,107,105,101,105,},
    {102,102,102,106,107,105,111,104,105,102,111,111,102,108,104,},
    {103,108,105,107,108,108,101,107,105,111,106,102,106,107,107,},
    {104,104,108,102,101,107,107,105,106,101,105,104,111,107,107,},
    {105,107,111,101,105,111,101,101,104,105,105,108,105,102,111,},
    {104,101,106,108,102,103,111,105,107,103,106,108,101,102,107,},
    {103,108,102,108,106,104,101,105,108,108,108,105,106,111,106,},
    {104,102,102,106,103,111,102,102,103,103,108,102,111,108,105,},
    {104,102,103,105,108,111,102,103,101,102,107,106,107,107,111,},
    {103,105,106,107,102,111,107,107,103,103,102,102,103,106,103,},
    {111,102,103,105,103,102,102,103,107,105,106,105,111,111,106,},
    {107,106,105,101,106,111,105,105,103,104,106,102,111,104,101,},
    {103,107,107,101,105,106,106,106,102,108,111,103,107,103,105,},
    {101,108,102,107,101,103,111,101,106,105,105,105,111,104,101,},
    {101,104,104,108,103,104,104,101,106,106,105,105,105,102,103,},
    {101,103,103,111,101,102,106,103,105,107,101,108,111,107,106,},
    {111,102,107,103,101,106,103,107,111,102,102,101,111,106,101,},
    {108,105,106,104,107,106,105,104,101,106,105,105,105,102,105,},
    {102,101,103,107,105,106,106,104,101,108,105,106,106,107,101,},
    {103,105,101,108,105,105,102,106,105,102,107,103,111,104,101,},
    {104,105,101,106,102,106,103,107,101,104,105,105,111,102,103,},
    {106,108,108,111,106,106,103,105,101,105,101,101,103,105,111,},
    {106,108,105,108,111,101,105,103,103,106,103,101,103,111,103,},
    {103,105,102,102,105,107,107,107,103,107,103,103,108,106,107,},
    {104,104,102,111,105,105,102,102,102,107,101,104,106,108,102,},
    {105,111,101,103,105,103,104,105,107,107,107,108,102,103,106,},
    {106,104,111,102,107,102,111,101,103,101,103,101,105,102,104,},
    {101,108,103,103,101,111,111,104,104,106,106,106,105,104,103,},
    {108,103,105,106,111,101,107,106,103,111,107,106,102,108,105,},
    {108,105,101,105,106,106,108,103,111,105,102,102,105,111,103,},
    {103,111,102,103,104,108,111,102,101,111,107,103,102,102,102,},
    {107,101,107,106,104,104,106,105,107,107,101,108,104,111,105,},
    {104,108,102,101,105,106,105,101,102,103,108,102,102,102,102,},
    {101,105,111,103,105,105,111,101,105,101,103,103,102,105,104,},
    {101,107,107,101,102,111,101,107,107,108,104,107,108,106,101,},
    {107,104,101,105,105,103,105,105,101,102,103,105,108,102,101,},
    {108,107,103,108,106,102,108,106,102,104,101,103,104,104,111,},
    {111,106,103,101,103,103,105,105,107,103,103,105,105,107,102,},
    {108,103,106,101,103,111,104,108,105,101,101,107,105,105,105,},
    {111,106,106,104,107,108,103,101,102,106,101,103,108,101,102,},
    {105,107,108,102,103,103,107,105,105,103,104,105,106,111,106,},
    {105,107,108,102,105,103,104,105,103,101,111,102,102,102,104,},
    {102,101,103,103,108,111,104,102,107,107,105,107,107,106,107,},
    {101,106,106,104,111,104,103,103,106,101,101,102,107,107,107,},
    {105,102,111,101,105,108,105,108,102,101,111,102,103,106,111,},
    {105,105,102,111,111,104,106,103,111,104,103,102,104,102,105,},
    {102,101,102,108,105,111,103,107,111,104,111,104,104,106,103,},
}

--必中开奖列表的索引表
--key为押注线数，value可选组合列表
local HitLottery_index_list = {
    --押n线必中的组合,组合倍率均大于1，不超过20
    [1] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,},
    [2] = {17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,},
    [3] = {33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,},
    [4] = {49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,},
    [5] = {65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,},
    [6] = {81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,},
    [7] = {97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,},
    [8] = {113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,},
    [9] = {129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,},
}

-------------------------------
-------------------------------
---工具类

--
--获得系统输钱上限
--
function SlotTool.get_system_lose_limit(gamename)
    local loselimit = 0
    local S = SlotTool.get_static_inventory_from_redis(gamename)
    if S < 0 then
        loselimit = SystemLoseLimit_Base
    else
        loselimit = math.floor(S * SystemLoseLimit_Factor) + SystemLoseLimit_Base
    end

    return loselimit
end

--
--获得返钱数
--
function SlotTool.get_rtm(line_num, picture_list, base_score)
    local total_score = 0
    local prize_list = SlotTool.check_betlines_result(line_num,picture_list,true)
    for _,item in pairs(prize_list.spin_result) do
        local id = item.prize_id
        total_score = total_score + base_score * (Odds_list[id] or 0)
    end
    for _,item in pairs(prize_list.littemary_prize_list) do
        total_score = total_score + base_score * (item.total_multi or 0)
    end

    return total_score
end

--
--检测亏损值是否超过输钱上限
--
function SlotTool.check_is_greater_loselimit(line_num, picture_list, base_score, is_robot_banker, loselimit)
    local total_bet = line_num * base_score
    local rtm = SlotTool.get_rtm(line_num, picture_list, base_score)
    local ksz = total_bet - rtm
    if (is_robot_banker and ksz < -loselimit)
    or (not is_robot_banker and ksz > loselimit) then
        return true,rtm
    end

    return false,rtm
end

--更新图标概率表
function SlotTool.update_picture_prob_list()
    local prob_list = {}
    local total_weight_list = {}

    for i,cols in pairs(Weight_list) do 
        local total_weight = 0
        for id,w in pairs(cols) do
            total_weight = total_weight + w
        end
        total_weight_list[i] = total_weight

        prob_list[i] = {}
        local total_prob = 0
        for id,w in pairs(cols) do
            prob_list[i][id] = w / total_weight
            total_prob = total_prob + prob_list[i][id]
        end
        
        --总概率应为1
        if math.floor(total_prob * 100) ~= 100 then
            filelog.sys_error("total probability not equal to 1!",total_prob)
        end
    end
    
    return prob_list,total_weight_list
end

--
--获取开奖类型
--返回 LotteryType类型
--
function SlotTool.get_lottery_type(gamename, base_score)
    --获取库存值
    local inventory = SlotTool.get_static_inventory_from_redis(gamename)

    local item = nil
    local s = inventory / 100
    if s <= -50000 then
        item = S_list[1]
    elseif s > -50000 and s < -10000 then
        item = S_list[2]
    elseif s >= -10000 and s < -1000 then
        item = S_list[3]
    elseif s >= -1000 and s <= 5000 then
        item = S_list[4]
    elseif s > 5000 and s <= 20000 then
        item = S_list[5]
    elseif s > 20000 and s <= 100000 then
        item = S_list[6]
    elseif s > 100000 then
        item = S_list[7]
    end

    --根据概率获取随机开奖类型
    local r = base.get_random(1, 100)
    local hit = math.floor(item.hit * 100)
    local nohit = hit + math.floor(item.nohit * 100)
    local normal = nohit + math.floor(item.normal * 100) 
    if r <= hit then
        return LotteryType.LOTTERY_TYPE_HIT
    elseif r <= nohit then
        return LotteryType.LOTTERY_TYPE_NOHIT
    elseif r <= normal then
        return LotteryType.LOTTERY_TYPE_NORMAL
    end
end

--
--获得纯随机结果
--
function SlotTool.get_real_random_result()
    local col_num = 5
    local row_num = 3
    local real_picture_id = {101,102,103,104,105,106,107,108,111}

    --随机每一个格子
    local result_list = {}
    for i = 1,row_num do
        for j = 1,col_num do
            local key = base.get_random(1,#real_picture_id)
            table.insert(result_list,real_picture_id[key])
        end
    end
    
    return result_list
end

--
--获取必中随机结果
--
function SlotTool.get_musthit_random_result(line_num)
    if not HitLottery_index_list or not HitLottery_index_list[line_num] then
         HitLottery_list,HitLottery_index_list = SlotTool.gen_musthit_list()
    end

    local maybe_list = HitLottery_index_list[line_num]
    local key = base.get_random(1, #maybe_list)
    return tabletool.deepcopy(HitLottery_list[key])
end

--
--获取4~10倍的必中随机结果
--
function SlotTool.get_minmulti_musthit_random_result(line_num)
    if not HitLottery_minmulti_index_list or not HitLottery_minmulti_index_list[line_num] then
         HitLottery_minmulti_list,HitLottery_minmulti_index_list = SlotTool.gen_minmulti_musthit_list()
    end

    local maybe_list = HitLottery_minmulti_index_list[line_num]
    local key = base.get_random(1, #maybe_list)
    return tabletool.deepcopy(HitLottery_minmulti_list[key])
end

--
--获取必不中随机结果
--
function SlotTool.get_nohit_random_result()
    NoHitLottery_list = NoHitLottery_list or SlotTool.gen_nohit_list()
    local key = base.get_random(1, #NoHitLottery_list)
    return tabletool.deepcopy(NoHitLottery_list[key])
end

--
--获取普通随机结果
--
function SlotTool.get_normal_random_result()
    Total_weight_list = Total_weight_list or SlotTool.calculate_total_weight_list(Weight_list)

    local col_num = 5
    local row_num = 3

    --根据概率随机每一个格子
    local result_list = {}
    for i = 1,row_num do
        for j = 1,col_num do
            local id = SlotTool.get_random_result_by_weightlist(Weight_list[j],Total_weight_list[j])
            table.insert(result_list,id)
        end
    end

    return result_list
end

--
--产生一个随机旋转结果
--
function SlotTool.gen_random_spin_result(gamename, base_score, line_num)
    local result_list = nil
    local loselimit = SlotTool.get_system_lose_limit(gamename)

    --获取开奖类型,分：必中，必不中，随机开奖3种
    local lottery_type = SlotTool.get_lottery_type(gamename,base_score)

    local cnt = 0
    local total_score = 0
    while cnt < 20 do
        if lottery_type == LotteryType.LOTTERY_TYPE_HIT then        --必中开奖
            result_list = SlotTool.get_musthit_random_result(line_num)
        elseif lottery_type == LotteryType.LOTTERY_TYPE_NOHIT then  --必不中开奖
            result_list = SlotTool.get_nohit_random_result()
        else    --随机开奖
            result_list = SlotTool.get_normal_random_result()
        end
        local is_out,rtm = SlotTool.check_is_greater_loselimit(line_num,result_list,base_score,true,loselimit)
        if not is_out then
            total_score = rtm
            break
        end
        cnt = cnt + 1
    end
    if cnt >= 20 then
        result_list = SlotTool.get_nohit_random_result()
    end
    
    --未中奖时随机中小倍奖
    if total_score == 0 then
        local hit_prob = SlotTool.get_minmulti_musthit_prob(gamename)
        Minmulti_weight_list[1] = math.floor(hit_prob * 100)
        Minmulti_weight_list[0] = 100 - Minmulti_weight_list[1]
        local is_hit = SlotTool.get_random_result_by_weightlist(Minmulti_weight_list)
        if is_hit == 1 then
            result_list = SlotTool.get_minmulti_musthit_random_result(line_num)
        end
    end

    return result_list
end

--
--检测随机结果的正确性
--
function SlotTool.check_random_spin_result(spin_result)
    return true
end

--
--创建格式化赔率列表
--
function SlotTool.create_format_odds_list()
    local fmt_odds_list = {}

    for id,odds in pairs(Odds_list) do
        local val = tonumber(id) * 10000 + tonumber(odds)
        table.insert(fmt_odds_list,val)
    end
    
    return fmt_odds_list
end

--
--保存赔率列表到文件
--
function SlotTool.save_odds_list_to_file()
    local f = io.open("odds_list.lua","w+")
    if not f then
        filelog.print("open file error!")
        return
    end

    f:write("return { ")
    for id,odds in pairs(Odds_list) do
        local val = tonumber(id) * 10000 + tonumber(odds)
        f:write(tostring(val) .. ",")
    end
    f:write("}")
    f:close()
end

--
--生成必中列表
--
function SlotTool.gen_musthit_list(is_savefile)
    local musthit_list = {}
    local musthit_index_list = {}
    local max_odds = 20

    --每种线数生成16种
    for i = 1,9 do
        musthit_index_list[i] = {}
        --生成16种
        local cnt = 0
        while cnt < 16 do
            local result_list = SlotTool.get_real_random_result()
            local result = SlotTool.check_betlines_result(i,result_list,true)
            if #(result.spin_result) > 0 then
                local total_rate = 0
                for k,item in pairs(result.spin_result) do
                    local id = item.prize_id
                    total_rate = total_rate + (Odds_list[id] or 0)
                end
                for k,item in pairs(result.littemary_prize_list) do
                    total_rate = total_rate + (item.total_multi or 0)
                end
                if total_rate > i and total_rate <= max_odds then
                    table.insert(musthit_list,result_list)
                    table.insert(musthit_index_list[i],#musthit_list)
                    cnt = cnt + 1
                end
            end
        end
    end

    if not is_savefile then
        return musthit_list,musthit_index_list
    end

    --保存到文件
    local f = io.open("musthit_list.lua","w+")
    if not f then
        return musthit_list,musthit_index_list
    end

    f:write("return {\n")
    local str = "musthit_list = {\n"
    for i,item in ipairs(musthit_list) do
        str = str .. "    {"
        for k,v in ipairs(item) do
            str = str .. v .. ","
        end
        str = str .. "},\n"
    end
    str = str .. "  },\n"

    str = str .. "musthit_index_list = {\n"
    for i,item in ipairs(musthit_index_list) do
        str = str .. "    [" .. i .. "] = {"
        for k,v in ipairs(item) do
            str = str .. v .. ","
        end
        str = str .. "},\n"
    end
    str = str .. "  },\n"

    f:write(str)
    f:write("}")
    f:close()

    return musthit_list,musthit_index_list
end

--
--生成小倍必中列表
--
function SlotTool.gen_minmulti_musthit_list(is_savefile)
    local musthit_list = {}
    local musthit_index_list = {}
    local max_odds = 10
    local min_odds = 4

    --每种线数生成16种,9线生成1000
    for i = 1,9 do
        musthit_index_list[i] = {}
        --生成16种
        local cnt = 0
        local total_num = 16
        if i == 9 then
            total_num = 1000
        end
        while cnt < total_num do
            local result_list = SlotTool.get_real_random_result()
            local result = SlotTool.check_betlines_result(i,result_list,true)
            if #(result.spin_result) > 0 then
                local total_rate = 0
                for k,item in pairs(result.spin_result) do
                    local id = item.prize_id
                    total_rate = total_rate + (Odds_list[id] or 0)
                end
                for k,item in pairs(result.littemary_prize_list) do
                    total_rate = total_rate + (item.total_multi or 0)
                end
                if total_rate >= min_odds and total_rate <= max_odds then
                    table.insert(musthit_list,result_list)
                    table.insert(musthit_index_list[i],#musthit_list)
                    cnt = cnt + 1
                end
            end
        end
    end

    if not is_savefile then
        return musthit_list,musthit_index_list
    end

    --保存到文件
    local f = io.open("musthit_minmulti_list.lua","w+")
    if not f then
        return musthit_list,musthit_index_list
    end

    f:write("return {\n")
    local str = "musthit_minmulti_list = {\n"
    for i,item in ipairs(musthit_list) do
        str = str .. "    {"
        for k,v in ipairs(item) do
            str = str .. v .. ","
        end
        str = str .. "},\n"
    end
    str = str .. "  },\n"

    str = str .. "musthit_minmulti_index_list = {\n"
    for i,item in ipairs(musthit_index_list) do
        str = str .. "    [" .. i .. "] = {"
        for k,v in ipairs(item) do
            str = str .. v .. ","
        end
        str = str .. "},\n"
    end
    str = str .. "  },\n"

    f:write(str)
    f:write("}")
    f:close()

    return musthit_list,musthit_index_list
end

--
--生成必不中列表
--
function SlotTool.gen_nohit_list(is_savefile)
    local nohit_list = {}
    local cnt = 0

    --生成36种
    while cnt < 36 do
        local result_list = SlotTool.get_real_random_result()
        local result = SlotTool.check_betlines_result(9,result_list,true)
        if #(result.spin_result) == 0 then
            table.insert(nohit_list,result_list)
            cnt = cnt + 1
        end
    end
    
    if not is_savefile then
        return nohit_list
    end

    --保存到文件
    local f = io.open("nohit_list.lua","w+")
    if not f then
        return nohit_list
    end

    f:write("return {\n")
    local str = ""
    for i,item in ipairs(nohit_list) do
        str = str .. "  {"
        for k,v in ipairs(item) do
            str = str .. v .. ","
        end
        str = str .. "},\n"
    end
    f:write(str)
    f:write("}")
    f:close()

    return nohit_list
end

--
--获取小倍必中概率
--
function SlotTool.get_minmulti_musthit_prob(gamename)
    local musthit_prob = 0.7    --默认70%
    local key = (gamename or "") .. "_minmulti_musthit_prob"
    local result,data = redisdao.query_data(".gmmqredis", "get", key)
    if result and data then
        musthit_prob = tonumber(data) or 0.7
        if musthit_prob < 0 or musthit_prob > 1 then
            musthit_prob = 0.7
        end
    end
    
    return musthit_prob
end

--
--保存奖励记录
--
function SlotTool.save_prize_records(gamename, award_list)
    local records = {}
    local key = (gamename or "") .. "_prize_records"
    local result,data = redisdao.query_data(".gmmqredis", "get", key)
    if result and data then
        records = json.decode(data) or {}
    end
    
    records.total_count = (tonumber(records.total_count) or 0) + 1
    for _,item in pairs(award_list) do
        local id = tostring(item.prize_id)
        local line = tostring(item.line)
        records[line] = records[line] or {}
        records[id] = (tonumber(records[id]) or 0) + 1
        records[line][id] = (tonumber(records[line][id]) or 0) + 1
        records[line]["total_count"] = (tonumber(records[line]["total_count"]) or 0) + 1
    end
    redisdao.query_data(".gmmqredis", "set", key, json.encode(records))

    ---------------------------------

    --辅助函数1
    local function helper_func(val)
        local cnt = 0
        local tmp = val
        while val >= 10 do
            val = math.floor(val / 10)
            cnt = cnt + 1
        end
        if math.floor(10^cnt) == tmp then
            return true
        end
        return false
    end

    --辅助函数2
    local function func(records)
        local porp_list = {}
        local subprop_list = {}
        local cnt = records.total_count or 0
        if cnt == 0 then
            return
        end

        for k,v in pairs(records) do
            if type(v) ~= "table" and k ~= "total_count" then
                v = tonumber(v) or 0
                porp_list[k] = string.format("%g%%",math.floor(v / cnt * 10000) / 100)
            elseif k == "total_count" then
                porp_list[k] = v
            else
                subprop_list[k] = func(v)
            end
        end
        return porp_list,subprop_list
    end

    --开奖次数每增加10倍，统计一次概率
    if helper_func(records.total_count) then
        local porp_list,subprop_list = func(records)
        filelog.sys_obj("prop_list", records.total_count, porp_list, "=================\n", subprop_list)
    end
    ---------------

    return true
end

--[Comment]
--根据图标id从转盘列表获取一个随机位置
--
function SlotTool.get_random_pos_by_picture_id(picture_id)
    --随机获取一个位置
    if Picture_index_map_list and Picture_index_map_list[picture_id] then
        local len = #(Picture_index_map_list[picture_id])
        if len > 0 then
            local pos = base.get_random(1,len)
            return Picture_index_map_list[picture_id][pos]
        end
    end
    
end

--
--获得小玛丽游戏奖励
--
function SlotTool.get_littlemary_spin_result(cur_spin_num, last_spin_result)
    local outter_weight_list = Littlemary_weight_list[1]
    local weapons_weight_list = Littlemary_weight_list[2]
    local links_weight_list = Littlemary_weight_list[3]
    
    local total_w = SlotTool.calculate_total_weight(outter_weight_list)
    local all_picture_id = {101,102,103,104,105,106,107,108}
    
    local prize_id = nil
    local weapons_num = 0
    local exit_id = SpecialPictureId.SPECIAL_PICTURE_ID_EXIT
    local outter_id = SlotTool.get_random_result_by_weightlist(outter_weight_list, total_w)
    if cur_spin_num == 5 then    --单次小玛丽最多转5轮
        outter_id = exit_id
    end
    if outter_id == 0 then    --未中奖
        local r = base.get_random(1, #all_picture_id)
        outter_id = all_picture_id[r]
    elseif outter_id == exit_id then    --游戏结束

    else    --外圈中奖,内圈必出外圈图标至少1个
        if weapons_weight_list[prize_id] then    --是否出双武器
            weapons_num = SlotTool.get_random_result_by_weightlist(weapons_weight_list[prize_id])
        else
            weapons_num = 1
        end
        prize_id = outter_id
    end
    
    --内圈开始图标列表
    local init_picture_list = {}
    if not last_spin_result then
        for i = 1,4 do
            local r = base.get_random(1, #all_picture_id)
            table.insert(init_picture_list,all_picture_id[r]) 
        end
    else
        init_picture_list = tabletool.deepcopy(last_spin_result.end_picture_list)
    end
    
    --内圈结束图标列表
    local end_picture_list = nil
    
    --是否出3连,双武器和3连互斥
    local first_id = nil
    if weapons_num < 2 then
        local link_num = SlotTool.get_random_result_by_weightlist(links_weight_list)
        if link_num > 0 then
            local r = base.get_random(1, #all_picture_id)
            first_id = all_picture_id[r]
            if first_id == prize_id then
                first_id = all_picture_id[r+1] or all_picture_id[r-1]
            end
            if link_num == SpecialPictureId.SPECIAL_PICTURE_ID_LEFT_THREE_LINK then
                end_picture_list = {first_id,first_id,first_id,prize_id}
            elseif link_num == SpecialPictureId.SPECIAL_PICTURE_ID_RIGHT_THREE_LINK then
                end_picture_list = {[1]=prize_id, [2]=first_id, [3]=first_id, [4]=first_id}
            elseif weapons_num == 0 and link_num == SpecialPictureId.SPECIAL_PICTURE_ID_FOUR_LINK then
                end_picture_list = {first_id,first_id,first_id,first_id}
            end
        end
        
    end
    
    --插入外圈中奖图标
    if not end_picture_list then
        end_picture_list = {}
        for i = 1,weapons_num do
            table.insert(end_picture_list,prize_id)
        end
    end

    --补充其他图标，不能为outter_id
    for i = 1,4 do
        if not end_picture_list[i] then
            local r = base.get_random(1, #all_picture_id)
            local id = all_picture_id[r]
            if id == outter_id or id == first_id then
                r = r % 8 + 1
                id = all_picture_id[r]
            end
            if i == 3 and end_picture_list[1] == end_picture_list[2] and id == end_picture_list[2] then
                r = r % 8 + 1
                id = all_picture_id[r]
            end
            if i == 4 and end_picture_list[2] == end_picture_list[3] and id == end_picture_list[3] then
                r = r % 8 + 1
                id = all_picture_id[r]
            end
            end_picture_list[i] = id
        end
    end
    
    --非3连时，随机排列图标
    if first_id == nil then
        for i = 1,4 do
            local x,y = base.get_random(1,4), base.get_random(1,4)
            end_picture_list[x],end_picture_list[y] = end_picture_list[y],end_picture_list[x]
        end
    end
    
    --计算单圈中奖倍数
    local total_odds = 0
    local inner_prize_id = nil
    for _,id in pairs(end_picture_list) do
        if id == prize_id then
            total_odds = total_odds + (Littlemary_odds_list[prize_id] or 0)
        end
    end
    if end_picture_list[2] == end_picture_list[3] then
        --左3连
        local is_left_link = nil
        if end_picture_list[1] == end_picture_list[2] then
            is_left_link = SpecialPictureId.SPECIAL_PICTURE_ID_LEFT_THREE_LINK
            inner_prize_id = is_left_link
        end
        
        --右3连
        local is_right_link = nil
        if end_picture_list[3] == end_picture_list[4] then
            is_right_link = SpecialPictureId.SPECIAL_PICTURE_ID_RIGHT_THREE_LINK
            inner_prize_id = is_right_link
        end
        
        --4连
        local is_four_link = nil
        if is_left_link and is_right_link then
            is_four_link = SpecialPictureId.SPECIAL_PICTURE_ID_FOUR_LINK
            inner_prize_id = is_four_link
        end
        
        local link_id = (is_four_link or is_left_link or is_right_link) or 0
        total_odds = total_odds + (Littlemary_odds_list[link_id] or 0)
    end
    
    --设置外圈旋转开始位置
    local start_pos = 1
    if last_spin_result then
        start_pos = last_spin_result.end_pos
    end
    
    --设置外圈旋转结束位置
    local end_pos = SlotTool.get_random_pos_by_picture_id(outter_id)
    
    --返回单圈旋转结果
    local single_spin_result = {
        start_pos = start_pos,
        end_pos = end_pos,
        cur_multi = total_odds,
        prize_id = prize_id,
        init_picture_list = init_picture_list,
        end_picture_list = end_picture_list,
        outter_id = outter_id,
        inner_prize_id = inner_prize_id,
    }
    
    return single_spin_result
end

--
--检测是否触发小玛丽游戏
--
function SlotTool.check_littlemary_result(result_list, picture_list)
    local littlemary_num = 0
    local bar_id = SpecialPictureId.SPECIAL_PICTURE_ID_BAR
    
    --获得图片数组某个元素值
    local function get_picture_elem(picture_list, point)
        local row,col = math.floor(point / 10),point % 10
        local pos = (row - 1) * 5 + col
        return picture_list[pos]
    end
    
    --检测是否触发小玛丽游戏，左起或右起中3个以上水浒传
    local min_num = 3
    for _,item in pairs(result_list) do
        local bar_num = 0
        local check_pos = nil
        --检测左边
        for i,point in ipairs(item.prize_elem_list) do
            local id = get_picture_elem(picture_list,point)
            if id == bar_id then
                bar_num = bar_num + 1
            else
                check_pos = i
                break
            end
        end
        if bar_num >= min_num then
            littlemary_num = littlemary_num + (bar_num - 2)
        end
        --检测右边
        if #(item.prize_elem_list) == 5 and check_pos then
            bar_num = 0
            for i = 5,1,-1 do
                local point = item.prize_elem_list[i]
                local id = get_picture_elem(picture_list,point)
                if id == bar_id then
                    bar_num = bar_num + 1
                else
                    break
                end
            end
            if bar_num >= min_num then
                littlemary_num = littlemary_num + (bar_num - 2)
            end
        end
    end
    
    --获得小玛丽游戏结果
    local cur_spin_num = 0
    local cur_total_multi = 0
    local last_spin_result = nil
    local spin_prize_list = {}
    local littemary_prize_list = {}
    while littlemary_num > 0 do
        cur_spin_num = cur_spin_num + 1
        local single_spin_result = SlotTool.get_littlemary_spin_result(cur_spin_num,last_spin_result)
        cur_total_multi = cur_total_multi + (single_spin_result.cur_multi or 0)
        table.insert(spin_prize_list,single_spin_result)
        if single_spin_result.outter_id == SpecialPictureId.SPECIAL_PICTURE_ID_EXIT then
            local littlemary_prizeitem = {
                spin_prize_list = spin_prize_list,
                total_multi = cur_total_multi,
            }
            table.insert(littemary_prize_list,littlemary_prizeitem)
            cur_spin_num = 0
            cur_total_multi = 0
            spin_prize_list = {}
            littlemary_num = littlemary_num - 1
        end
        last_spin_result = single_spin_result
    end

    return littemary_prize_list
end

--
--检查玩家压注线中奖情况
--
function SlotTool.check_betlines_result(line_num, picture_list, is_check_right)
    local result_list = {}
    
    --[[
    flag = true
    if not flag then
        picture_list = {
            104,107,108,108,105,
            104,107,101,111,111,
            102,101,104,103,105,
        }
    end
    --]]
    
    --获得图片数组某个元素值
    local function get_picture_elem(picture_list, point)
        local row,col = math.floor(point / 10),point % 10
        local pos = (row - 1) * 5 + col
        return picture_list[pos]
    end

    local bar_id = SpecialPictureId.SPECIAL_PICTURE_ID_BAR

    --检测是否全屏相同图标,水浒传也算相同图标
    local is_fullpicture = true
    for _,id in pairs(picture_list) do
        if id ~= picture_list[1] and id ~= bar_id then
            is_fullpicture = false
            break
        end
    end

    for i = 1,line_num do
        local points = line_list[i]
        local len = #points
        local s,e = 2,len - 1
        local left_cnt,right_cnt = 1,1
        local left_val = get_picture_elem(picture_list,points[1])
        local right_val = get_picture_elem(picture_list,points[len])
        while s <= len do
            local lval = get_picture_elem(picture_list,points[s])
            if (lval == left_val or lval == bar_id) then
                left_cnt = left_cnt + 1
                s = s + 1
            elseif left_val == bar_id then
                left_val = lval
                left_cnt = left_cnt + 1
                s = s + 1
            else
                break
            end
        end
        while e >= 1 do
            local rval = get_picture_elem(picture_list,points[e])
            if (rval == right_val or rval == bar_id) then
                right_cnt = right_cnt + 1
                e = e - 1
            elseif right_val == bar_id then
                right_val = rval
                right_cnt = right_cnt + 1
                e = e - 1
            else
                break
            end
        end

        --左右相同，且全连
        if left_val == right_val and left_cnt >= len then
             right_cnt = 0
        end

        --保存结果
        if left_cnt > 1 then
            local prize_id = left_cnt * 1000 + left_val
            if is_fullpicture then 
                prize_id = prize_id + 1000 
            end
            if Odds_list[prize_id] then
                local item = {
                    line = i,
                    prize_id = prize_id,
                    prize_elem_list = {},
                }
                for j = 1,left_cnt do
                    table.insert(item.prize_elem_list,points[j])
                end
                table.insert(result_list,item)
            end
        end
        if is_check_right and right_cnt > 1 then
            local prize_id = right_cnt * 1000 + right_val
            if is_fullpicture then 
                prize_id = prize_id + 1000 
            end
            if Odds_list[prize_id] then
                local item = {
                    line = i,
                    prize_id = prize_id,
                    prize_elem_list = {},
                }
                for k = len,len-right_cnt+1,-1 do
                    table.insert(item.prize_elem_list,points[k])
                end
                table.insert(result_list,item)
            end
        end
    end
    
    --检测小玛丽中奖情况
    local littemary_prize_list = SlotTool.check_littlemary_result(result_list,picture_list) or {}
    --[[
    if not flag then
        filelog.print(result_list,littemary_prize_list)
        flag = true
    end
    --]]
    
    return {spin_result = result_list,littemary_prize_list = littemary_prize_list}
end

--
--根据开奖结果获取随机骰子点数
--
function SlotTool.get_dices_point_by_result(result_id)
    local dice_one = 0
    local dice_two = 0
    
    if result_id == ELHJBetBtnId.BET_BTN_ID_LARGE then        --大,8~12
        dice_one = base.get_random(2,6)
        dice_two = base.get_random(8-dice_one,6)
    elseif result_id == ELHJBetBtnId.BET_BTN_ID_SMALL then    --小,2~6
        dice_one = base.get_random(1,5)
        dice_two = base.get_random(1,6-dice_one)
    elseif result_id == ELHJBetBtnId.BET_BTN_ID_TIE then      --和,7
        dice_one = base.get_random(1,6)
        dice_two = 7 - dice_one
    else
        dice_one = base.get_random(1,6)
        dice_two = base.get_random(1,6)
        
        local total_point = dice_one + dice_two
        if total_point < 7 then
            result_id = ELHJBetBtnId.BET_BTN_ID_SMALL
        elseif total_point > 7 then
            result_id = ELHJBetBtnId.BET_BTN_ID_LARGE
        else
            result_id = ELHJBetBtnId.BET_BTN_ID_TIE
        end
    end
    
    --返回结果
    local result_list = {
        dice_one = dice_one,
        dice_two = dice_two,
        prize_id = result_id,
    }
    
    return result_list
end

--
--获取随机骰子结果
--
function SlotTool.get_random_dices_result(gamename, total_score, bet_item_id, base_score, line_num)
    local result_id = nil
    local all_item_list = {
        [ELHJBetBtnId.BET_BTN_ID_LARGE] = 100,
        [ELHJBetBtnId.BET_BTN_ID_SMALL] = 100,
        [ELHJBetBtnId.BET_BTN_ID_TIE] = 20,
    }
    
    local loselimit = SlotTool.get_system_lose_limit(gamename)

    --获取开奖类型,分：必中，必不中，随机开奖3种
    local lottery_type = SlotTool.get_lottery_type(gamename,total_score)
    if lottery_type == LotteryType.LOTTERY_TYPE_HIT then        --必中开奖
        result_id = bet_item_id
    elseif lottery_type == LotteryType.LOTTERY_TYPE_NOHIT then  --必不中开奖
        all_item_list[bet_item_id] = nil
        result_id = SlotTool.get_random_result_by_weightlist(all_item_list)
    else    --随机开奖
        result_id = SlotTool.get_random_result_by_weightlist(all_item_list)
    end
        
    --检测是否超过输上限,押中才检测
    if result_id == bet_item_id then
        local total_bet = line_num * base_score
        local rtm = total_score * ELHJDicesOddsList[result_id]
        local ksz = total_bet - rtm
        if (ksz < -loselimit) then    --超过输上限则必不中
            all_item_list[bet_item_id] = nil
            result_id = SlotTool.get_random_result_by_weightlist(all_item_list)
        end
    end
    
    return SlotTool.get_dices_point_by_result(result_id)
end

-------------------------------
----------
--外部接口

local CMD = {}

local cs = queue()

-----------------
----

--
--获取随机旋转结果
--
function CMD.get_random_spin_result(gamename, base_score, line_num)
    local cnt = 0
    while cnt < 100 do
        local spin_result = SlotTool.gen_random_spin_result(gamename, base_score, line_num)
        if SlotTool.check_random_spin_result(spin_result) then
            return spin_result
        end
        cnt = cnt + 1
    end

    return false
end

--
--获得线数组
--
function CMD.get_line_list()
    return tabletool.deepcopy(line_list)
end

--
--获取转盘奖励
--抽中钻石有概率触发
--
function CMD.get_turntable_prize(result_list)
    local diamond_id = SpecialPictureId.SPECIAL_PICTURE_ID_DIAMOND

    local diamond_num = 0
    for _,item in pairs(result_list) do
        local id = item.prize_id % 1000
        if id == diamond_id then
            local num = math.floor(item.prize_id / 1000)
            if num > diamond_num then
                diamond_num = num
            end
        end
    end
    
    if diamond_num < 3 then
        return
    end
     
    local weight_list = Turntable_weight_list[diamond_num]
    local idx = SlotTool.get_random_result_by_weightlist(weight_list)
    local odds = Truntable_odds_list[diamond_num][idx]

    return odds
end

--
--获得初始图片列表
--一个12 * 5的数组
--
function CMD.get_init_picture_list()
    return tabletool.deepcopy(Init_picture_list)
end

--
--检查玩家压注线中奖情况
--
function CMD.check_betlines_result(line_num, picture_list, is_check_right)
    return SlotTool.check_betlines_result(line_num, picture_list, is_check_right)
end

--
--处理开奖
--
function CMD.handle_open_jackpot(gamename, jackpot_id, player_list, max_award_num)
    local award_list = {}
    local total_coin = 0
    
    --中奖玩家数不超过总人数1/2
    if not player_list or max_award_num < 1 
    or #player_list < 2 * max_award_num then
        return award_list,total_coin
    elseif #player_list < 20 * max_award_num then
        max_award_num = base.get_random(1,max_award_num)
    end 

    --获取奖池金额
    local jackpot_money = SlotTool.get_jackpot_from_redis(gamename,jackpot_id)
    
    --随机开奖
    local total_num = #player_list
    for _,item in pairs(player_list) do
        local r = base.get_random(1,total_num)
        if r <= max_award_num then
            local award_coin = 0
            local total_bet = math.floor(item.dur_total_bet / 100)
            if total_bet < 50 then          --下注低于50元
                if jackpot_money < 1500000 then    --奖池少于15000，获取0.02%
                    award_coin = math.floor(jackpot_money * 0.0002)
                else        --奖池大于15000，随机3～10元
                    award_coin = base.get_random(300,1000)
                end
            elseif total_bet < 1000 then    --下注50～1000
                if jackpot_money < 1500000 then    --奖池少于15000，获取0.04%
                    award_coin = math.floor(jackpot_money * 0.0004)
                else        --奖池大于15000，5+1%
                    award_coin = 500 + math.floor(jackpot_money * 0.01)
                end
            else       --下注1000及以上
                if jackpot_money < 1500000 then    --奖池少于500，获取0.08%
                    award_coin = math.floor(jackpot_money * 0.0008)
                else        --奖池大于15000，50+2%
                    award_coin = 5000 + math.floor(jackpot_money * 0.02)
                end
            end
            --最低中1块
            if award_coin < 100 then
                award_coin = base.get_random(100,200)
            end
            local award_item = {
                rid = item.rid,
                logo = item.logo,
                rolename = item.rolename,
                award_money_num = award_coin,
                last_bet_score = item.last_bet_score,
            }
            if (total_coin + award_coin) > jackpot_money then
                break
            end
            total_coin = total_coin + award_coin
            table.insert(award_list, award_item)
            if #award_list >= max_award_num then
                break
            end
        end
    end
    
    return award_list,total_coin
end

--
--保存奖励记录
--
function CMD.save_prize_records(gamename, award_list)
    return cs(SlotTool.save_prize_records,gamename,award_list)
end

--
--更新图标权值表
--
function CMD.update_picture_weight_list(new_w_list)
    if type(new_w_list) ~= "table" then
        return false
    end

    for k,v in pairs(new_w_list) do
        if Weight_list[k] and type(v) == "table" then
            for id,w in pairs(v) do
                if Weight_list[k][id] and w >= 0 then
                    Weight_list[k][id] = w
                end
            end
        end
    end
    
    --更新化概率表,总权值
    if next(new_w_list) ~= nil then
        Prob_list,Total_weight_list = SlotTool.update_picture_prob_list()
    end

    return true
end



--
--设置系统输钱上限
--
function CMD.set_system_lose_limit(loselimit_base, loselimit_factor)
    loselimit_base = loselimit_base or 0
    loselimit_factor = loselimit_factor or 0.02
    if loselimit_base < 0 or loselimit_factor < 0 then
        return false
    end
    SystemLoseLimit_Base = loselimit_base
    SystemLoseLimit_Factor = loselimit_factor

    return true
end

--
--处理结算结果
--@total_change 总变化值
--@total_water  总流水值
--@total_bet    玩家总下注
--
function CMD.handle_balance_result(gamename, total_change, total_water, total_bet, comment)
    local tax_rate = SlotTool.get_tax_rate_from_redis(gamename)
    local jackpot_rate = SlotTool.get_jackpot_rate_from_redis(gamename)
    local profit_val = math.floor(total_bet * tax_rate * 100) / 100
    local jackpot_val = math.floor(total_bet * jackpot_rate * 100) / 100
    local inventory_val = -total_change

    --更新收益值
    local result1 = SlotTool.update_system_profit(gamename, profit_val, comment)
    if result1 then
        inventory_val = inventory_val - profit_val
    end
    
    --更新奖池
    local result2 = SlotTool.update_system_jackpot(gamename, jackpot_val, comment)
    if result2 then
        inventory_val = inventory_val - jackpot_val
    end

    --更新库存值，扣除抽水
    local service_fee_rate = SlotTool.get_service_fee_rate_from_redis(gamename)
    local service_fee_val = math.floor(total_water * service_fee_rate * 100) / 100
    inventory_val = inventory_val - service_fee_val

    return SlotTool.update_system_inventory(gamename, inventory_val, comment)
end

--
--获取抽水率
--
function CMD.get_service_fee_rate(gamename)
    return SlotTool.get_service_fee_rate_from_redis(gamename)
end

--
--获取随机骰子结果
--
function CMD.get_random_dices_result(gamename, total_score, bet_item_id, base_score, line_num)
    return SlotTool.get_random_dices_result(gamename, total_score, bet_item_id, base_score, line_num)
end

-----------
--
--初始化
--
local function init()

    --初始化概率表
    Prob_list,Total_weight_list = SlotTool.update_picture_prob_list()
    
    --初始化转盘图标映射表
    Picture_index_map_list = {}
    for i,id in ipairs(Turntable_conf) do
        Picture_index_map_list[id] = Picture_index_map_list[id] or {}
        table.insert(Picture_index_map_list[id],i)
    end
    
    --初始化小倍必中组合
    HitLottery_minmulti_list,HitLottery_minmulti_index_list = SlotTool.gen_minmulti_musthit_list(true)
    
    --初始化必不中组合
    --NoHitLottery_list = SlotTool.gen_nohit_list(true)

    --初始化必中组合
    --HitLottery_list,HitLottery_index_list = SlotTool.gen_musthit_list(true)

    --保存赔率列表
    --SlotTool.save_odds_list_to_file()

    --filelog.print("init slot tool ok!")
end

-------------------
--
skynet.start(function()
    init()
    skynet.dispatch("lua",function(session, source, cmd, ...)
        local f = CMD[cmd]
        if f then
            skynet.retpack(f(...))
        else
            skynet.retpack()
        end
    end)
end)